package com.zhy.ble.demo.ui;

import android.bluetooth.BluetoothGatt;
import android.bluetooth.BluetoothGattCharacteristic;
import android.content.Context;
import android.content.DialogInterface;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.support.annotation.Nullable;
import android.support.v7.app.AlertDialog;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import android.widget.EditText;
import android.widget.RadioGroup;
import android.widget.TextView;

import com.afollestad.materialdialogs.MaterialDialog;
import com.bryan.autolayout.AutoLayoutActivity;
import com.bryan.common.utils.WeakHandler;
import com.bryan.common.utils.log.LogUtils;
import com.zhy.ble.demo.R;
import com.zhy.ble.demo.ToastMgr;
import com.zhy.ble.demo.load.LoadDialog;

import cn.com.heaton.bleLib.ble.Ble;
import cn.com.heaton.bleLib.ble.BleStates;
import cn.com.heaton.bleLib.ble.L;
import cn.com.heaton.bleLib.ble.callback.BleConnectCallback;
import cn.com.heaton.bleLib.ble.callback.BleNotiftCallback;
import cn.com.heaton.bleLib.ble.model.BleDevice;
import cn.com.heaton.bleLib.logic.HexUtil;
import cn.com.heaton.bleLib.logic.bean.BlackBean;
import cn.com.heaton.bleLib.logic.bean.DeviceInfo;
import cn.com.heaton.bleLib.logic.bean.RecordBean;
import cn.com.heaton.bleLib.logic.bean.TimeBean;
import cn.com.heaton.bleLib.logic.bean.WhiteBean;
import cn.com.heaton.bleLib.logic.notify.AuthCallBack;
import cn.com.heaton.bleLib.logic.notify.CommonCallBack;
import cn.com.heaton.bleLib.logic.notify.DeviceInfoCallBack;
import cn.com.heaton.bleLib.logic.notify.FetchTimeCallBack;
import cn.com.heaton.bleLib.logic.notify.OnBlackCallBack;
import cn.com.heaton.bleLib.logic.notify.OnRecordCallBack;
import cn.com.heaton.bleLib.logic.notify.OnWhiteCallBack;
import cn.com.heaton.bleLib.logic.notify.OpenDoorCallBack;


/**
 * 功能测试界面
 * Created by bryan on 2019/5/17.
 */
public class BleOperationActivity extends AutoLayoutActivity {

    private String TAG = "BleOperationActivity";

    /*一次蓝牙开门的最长时间*/
    public static final int Max_Connect_Time = 20 * 1000;

    //表示是否在连接设备
    private boolean isTryToConnectDevice = false;


    private Context mContext;
    private BleDevice mCurSelectRke;
    private TextView tvDevice;
    private TextView tvStatus;
    private EditText etWhite;
    private EditText etBlack;
    private EditText etRecord;


    private Ble<BleDevice> mBle;

    /**
     * 一些错误标志位，用于在message.arg2中传递
     */
    /*连接超时*/
    private static final int Error_CONNECT_TIME_OUT = -1;
    /*蓝牙服务可能有问题*/
    private static final int Error_Ble_Server = -2;


    /*开门的消息*/
    private static final int Msg_Connect_Device = 0x601;
    private static final int Msg_Open_Finish = 0x602;//开门结果，开门成功，或者失败，arg1 表示结果，0 表示成功，1表示失败，obj表示失败原因
    private static final int Msg_Connect_Success = 0x604;//连接成功
    private static final int Msg_Connect_Fail = 0x603;//连接失败
    private static final int Msg_Connect_OVer_Time = 0x605;//连接最大时长


    /*开门成功*/
    private static final int Ble_Open_Success = 0;
    /*开门失败*/
    private static final int Ble_Open_Fail = 1;


    private WeakHandler mHandler = new WeakHandler(new Handler.Callback() {
        @Override
        public boolean handleMessage(Message msg) {
            switch (msg.what) {
                case Msg_Connect_Device:
                    connect(mCurSelectRke);
                    break;
                case Msg_Connect_Success:
                    if (mHandler.hasMessages(Msg_Connect_OVer_Time)) {
                        mHandler.removeMessages(Msg_Connect_OVer_Time);
                    }
                    dismissLoading();
                    isTryToConnectDevice = false;
                    auth(mCurSelectRke);
                    tvStatus.setText(getConnectDesc(mCurSelectRke.getConnectionState()));
                    break;
                case Msg_Connect_Fail:
                    if (mHandler.hasMessages(Msg_Connect_OVer_Time)) {
                        mHandler.removeMessages(Msg_Connect_OVer_Time);
                    }
                    dismissLoading();
                    String reason = (String) msg.obj;
                    toast(reason);
                    tvStatus.setText(getConnectDesc(mCurSelectRke.getConnectionState()));
                    break;
                case Msg_Connect_OVer_Time:
                    showCommonDialog("提示", "连接超时，请重试");
                    disconnectDevice();
                    dismissLoading();
                    break;
            }
            return false;
        }
    });


    //链接失败重连次数
    private int retryCount = 0;
    /*连接失败最多重连次数*/
    private static final int Max_Retry_Count = 3;

    //是否是内置模式
    private boolean isInModel = true;
    //是否是AT模式
    private boolean isATModel = true;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_rke_sync);
        mContext = BleOperationActivity.this;
        mCurSelectRke = (BleDevice) getIntent().getSerializableExtra("BLE");
        if (mCurSelectRke == null) {
            ToastMgr.show("数据传递错误");
            finish();
            return;
        }
        tvDevice = findViewById(R.id.tv_device);
        tvStatus = findViewById(R.id.tv_status);
        etWhite = findViewById(R.id.et_white);
        etBlack = findViewById(R.id.et_black);
        etRecord = findViewById(R.id.et_record);

        findViewById(R.id.iv_back).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                finish();
            }
        });

        findViewById(R.id.btn_connect).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                startConnectDevice();
            }
        });
        findViewById(R.id.btn_open).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                openDoor(mCurSelectRke);
            }
        });
        findViewById(R.id.btn_disconnect).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                disconnectDevice();
            }
        });

        RadioGroup radioGroup = findViewById(R.id.radioGroup);
        radioGroup.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(RadioGroup radioGroup, int i) {
                if (i == R.id.btnIn) {
                    isInModel = true;
                } else if (i == R.id.btnOut) {
                    isInModel = false;
                }
            }
        });

        RadioGroup radioGroup2 = findViewById(R.id.radioGroup2);
        radioGroup2.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(RadioGroup radioGroup, int i) {
                if (i == R.id.btnAt) {
                    isATModel = true;
                } else if (i == R.id.btnTc) {
                    isATModel = false;
                }
            }
        });

        mBle = Ble.getInstance();
        if (mBle == null) {
            toast("数据异常，请重试");
            finish();
            return;
        }
        tvDevice.setText(mCurSelectRke.getBleName());
        tvStatus.setText(getConnectDesc(mCurSelectRke.getConnectionState()));
        startConnectDevice();

    }

    /**
     * 获取设备时间
     *
     * @param view
     */
    public void fetchTime(View view) {
        if (mCurSelectRke == null || !isDeviceConnected(mCurSelectRke)) {
            return;
        }
        showLoading();
        mBle.fetchTime(mCurSelectRke, new FetchTimeCallBack() {
            @Override
            public void onSuccess(TimeBean timeBean) {
                dismissLoading();
                String time = "当前设备时间：" + timeBean.formateTime;
                showCommonDialog("设备时间", time);
            }

            @Override
            public void onFail(String failReason) {
                dismissLoading();
                showCommonDialog("设备时间", "获取设备时间失败：" + failReason);
            }
        });
    }

    /**
     * 同步系统时间给蓝牙设备
     *
     * @param view
     */
    public void syncTime(View view) {
        if (mCurSelectRke == null || !isDeviceConnected(mCurSelectRke)) {
            return;
        }
        showLoading();
        mBle.sycnTime(mCurSelectRke, new CommonCallBack() {
            @Override
            public void onSuccess(String desc) {
                dismissLoading();
                showCommonDialog("时间同步", "时间同步成功！");
            }

            @Override
            public void onFail(String reason) {
                dismissLoading();
                showCommonDialog("时间同步", "时间同步失败:" + reason);

            }
        });
    }


    public void fetchVersion(View view) {
        if (mCurSelectRke == null || !isDeviceConnected(mCurSelectRke)) {
            return;
        }
        showLoading();
        mBle.fetchVersion(mCurSelectRke, new CommonCallBack() {


            @Override
            public void onSuccess(String desc) {
                dismissLoading();
                showCommonDialog("版本号", desc);
            }

            @Override
            public void onFail(String failReason) {
                dismissLoading();
                showCommonDialog("版本号", "获取版本号失败：" + failReason);
            }
        });
    }

    /**
     * 设置lora设备内置外置接口
     *
     * @param view
     */
    public void setInterface(View view) {
        if (mCurSelectRke == null || !isDeviceConnected(mCurSelectRke)) {
            return;
        }
        showLoading();
        mBle.setInterface(mCurSelectRke, isInModel, isATModel, new CommonCallBack() {
            @Override
            public void onSuccess(String desc) {
                dismissLoading();
                toast("设置成功");
                showCommonDialog("Lora设置", "设置成功");

            }

            @Override
            public void onFail(String reason) {
                dismissLoading();
                showCommonDialog("Lora设置", "设置失败：" + reason);

            }
        });


    }

    /**
     * 获取黑名单记录
     *
     * @param view
     */
    public void getBlack(View view) {

        String black = etBlack.getText().toString().trim();
        if (TextUtils.isEmpty(black)) {
            toast("请输入要查询的黑名单记录索引");
            return;
        }
        int index = -1;
        try {
            index = Integer.parseInt(black);
            if (index < 1 || index > 51200) {
                toast("无效输入，请重试。黑名单索引：1～51200");
                etRecord.setText("");
                return;

            }

            if (mCurSelectRke == null || !isDeviceConnected(mCurSelectRke)) {
                return;
            }

            showLoading();
            mBle.getBlack(mCurSelectRke, index, new OnBlackCallBack() {
                @Override
                public void onSuccess(BlackBean blackBean) {
                    dismissLoading();
                    StringBuilder sbContent = new StringBuilder();
                    sbContent.append("卡号：")
                            .append(blackBean.cardNo != null ? HexUtil.encodeHexStr(blackBean.cardNo) : "")
                            .append("\n")
                            .append("截止日期：")
                            .append(blackBean.formateTime);
                    showCommonDialog("黑名单记录", sbContent.toString());
                }

                @Override
                public void onFail(String failReason) {
                    dismissLoading();
                    showCommonDialog("黑名单记录", "获取记录失败，原因：" + failReason);
                }
            });
        } catch (Exception e) {
            e.printStackTrace();
            dismissLoading();
            toast("输入数据不合法，请重新输入");
            etBlack.setText("");
        }


    }

    /**
     * 获取白名单
     *
     * @param view
     */
    public void getWhite(View view) {
        String white = etWhite.getText().toString().trim();
        if (TextUtils.isEmpty(white)) {
            toast("请输入要查询的白名单记录索引");
            return;
        }
        int index = -1;
        try {
            index = Integer.parseInt(white);

            if (index < 1 || index > 51200) {
                toast("无效输入，请重试。白名单索引：1～51200");
                etRecord.setText("");
                return;

            }

            if (mCurSelectRke == null || !isDeviceConnected(mCurSelectRke)) {
                return;
            }

            showLoading();
            mBle.getWhite(mCurSelectRke, index, new OnWhiteCallBack() {
                @Override
                public void onSuccess(WhiteBean blackBean) {
                    dismissLoading();
                    StringBuilder sbContent = new StringBuilder();
                    sbContent.append("卡号：")
                            .append(blackBean.cardNo != null ? HexUtil.encodeHexStr(blackBean.cardNo) : "")
                            .append("\n")
                            .append("截止日期：")
                            .append(blackBean.formateTime);
                    showCommonDialog("白名单记录", sbContent.toString());
                }

                @Override
                public void onFail(String failReason) {
                    dismissLoading();
                    showCommonDialog("白名单记录", "获取记录失败，原因：" + failReason);
                }
            });
        } catch (Exception e) {
            e.printStackTrace();
            dismissLoading();
            toast("输入数据不合法，请重新输入");
            etWhite.setText("");
        }
    }


    /**
     * 获取开门记录
     *
     * @param view
     */
    public void getRecord(View view) {
        String record = etRecord.getText().toString().trim();
        if (TextUtils.isEmpty(record)) {
            toast("请输入要查询的开门记录索引");
            return;
        }
        int index = -1;
        try {
            index = Integer.parseInt(record);
            if (index < 1 || index > 100000) {
                toast("无效输入，请重试。开门记录索引：1～100000");
                etRecord.setText("");
                return;
            }

            if (mCurSelectRke == null || !isDeviceConnected(mCurSelectRke)) {
                return;
            }

            showLoading();
            mBle.getRecord(mCurSelectRke, index, new OnRecordCallBack() {
                @Override
                public void onSuccess(RecordBean recordBean) {
                    dismissLoading();
//                    if (recordBean.cardLength == 0) {
//                        showCommonDialog("开门记录", "没有获取到对应的开门记录");
//
//                    } else {
                    StringBuilder sbContent = new StringBuilder();
                    sbContent.append("卡号：")
                            .append(recordBean.cardNo != null ? HexUtil.encodeHexStr(recordBean.cardNo) : "")
                            .append("\n")
                            .append("开门时间：")
                            .append(recordBean.formateTime)
                            .append("开门类型：")
                            .append(recordBean.recordType);
                    showCommonDialog("开门记录", sbContent.toString());
//                    }
                }

                @Override
                public void onFail(String failReason) {
                    dismissLoading();
                    showCommonDialog("开门记录", "开门记录获取失败，" + failReason);
                }
            });
        } catch (Exception e) {
            e.printStackTrace();
            dismissLoading();
            toast("输入数据不合法，请重新输入");
            etRecord.setText("");
        }
    }


    /**
     * 查询设备信息
     *
     * @param view
     */
    public void getDeviceInfo(View view) {

        if (mCurSelectRke == null || !isDeviceConnected(mCurSelectRke)) {
            return;
        }

        showLoading();
        mBle.getDeviceInfo(mCurSelectRke, new DeviceInfoCallBack() {
            @Override
            public void onSuccess(DeviceInfo deviceInfo) {
                dismissLoading();
                StringBuilder sbContent = new StringBuilder();
                sbContent.append("Lora模式:")
                        .append(deviceInfo.loraModel == 0 ? "内置" : "外置")
                        .append("\n")
                        .append("白名单数量：")
                        .append(deviceInfo.whiteNoInt)
                        .append("\n")
                        .append("黑名单数量：")
                        .append(deviceInfo.blackNoInt)
                        .append("\n")
                        .append("开门记录数量：")
                        .append(deviceInfo.recordNoInt);
                showCommonDialog("设备信息", sbContent.toString());
            }

            @Override
            public void onFail(String failReason) {
                dismissLoading();
                showCommonDialog("设备信息", "获取设备信息失败。原因：" + failReason);

            }
        });
    }

    /**
     * 主动开始连接设备
     */
    private void startConnectDevice() {

        isTryToConnectDevice = true;
        retryCount = 0;

        //设置超时连接时长
        mHandler.sendEmptyMessageDelayed(Msg_Connect_OVer_Time, Max_Connect_Time);

        //设置连接超时
        mHandler.sendEmptyMessage(Msg_Connect_Device);


    }

    private boolean isDeviceConnected(BleDevice bleDevice) {
        if (bleDevice.getConnectionState() == BleStates.BleStatus.CONNECTED) {
            return true;
        } else {
            showCommonDialog("提示", "设备未连接，请先点击连接按钮连接设备");
            return false;
        }
    }

    @Override
    protected boolean isNeedAutoLayout() {
        return true;
    }

    /**
     * 设备授权
     */
    private void auth(BleDevice bleDevice) {
        if (isDeviceConnected(bleDevice)) {
            showLoading();
            mBle.auth(bleDevice, new AuthCallBack() {
                @Override
                public void authSuccess() {
                    dismissLoading();
                    toast("授权完成");

                }

                @Override
                public void authFail() {
                    disconnectDevice();
                    showCommonDialog("授权", "设备授权失败，请检查设备是否正确");
                }
            });
        } else {
            showCommonDialog("授权", "设备未连接，请连接上蓝牙设备");

        }
    }

    /**
     * 链接设备
     */
    private void connect(BleDevice bleDevice) {
        if (bleDevice.getConnectionState() != BleStates.BleStatus.CONNECTED) {
            if (mBle != null) {
                showLoading();
                mBle.connect(bleDevice, connectCallback);
            } else {
                isTryToConnectDevice = false;
                Message overtimeMsg = new Message();
                overtimeMsg.arg1 = Error_Ble_Server;
                overtimeMsg.what = Msg_Connect_Fail;
                overtimeMsg.obj = "连接失败，请退出重试";
                mHandler.sendMessage(overtimeMsg);
            }
        } else {
            ToastMgr.show("设备已连接");
            mHandler.sendEmptyMessage(Msg_Connect_Success);
        }
    }

    /**
     * 断开设备连接
     */
    private void disconnectDevice() {
        if (mBle != null) {
            if (mCurSelectRke != null) {
                mBle.disconnect(mCurSelectRke, connectCallback);
                tvStatus.setText(getConnectDesc(mCurSelectRke.getConnectionState()));
            }
        }
    }


    @Override
    protected void onDestroy() {
        dismissLoading();
        disconnectDevice();
        mHandler.removeCallbacksAndMessages(null);
        super.onDestroy();
    }

    /***
     * 组装开门指令
     */
    private void openDoor(BleDevice bleDevice) {
        if (mCurSelectRke == null || !isDeviceConnected(mCurSelectRke)) {
            return;
        }

        showLoading();
        mBle.openDoor(bleDevice, new OpenDoorCallBack() {
            @Override
            public void openSuccess() {
                dismissLoading();
                showCommonDialog("开门提示", "开门成功");

            }

            @Override
            public void openFail(byte code) {
                dismissLoading();
                showCommonDialog("开门提示", "开门失败,错误代码:" + code);
            }
        });
    }


    public String getConnectDesc(int code) {
        String result = "未连接";
        switch (code) {
            case BleStates.BleStatus.CONNECTED:
                result = "已连接";
                break;
            case BleStates.BleStatus.CONNECTING:
                result = "连接中";
                break;
            case BleStates.BleStatus.DISCONNECT:
                result = "未连接";
                break;
        }
        return result;
    }

    /**
     * 连接的回调
     */
    private BleConnectCallback<BleDevice> connectCallback = new BleConnectCallback<BleDevice>() {
        @Override
        public void onConnectionChanged(BleDevice device) {
            Log.e(TAG, "onConnectionChanged: " + device.getConnectionState());
            Log.e(TAG, "onConnectionChanged: current thread:" + Thread.currentThread().getName());

            if (mCurSelectRke != null && mCurSelectRke.getBleName().equals(device.getBleName())) {
                if (device.getConnectionState() == BleStates.BleStatus.DISCONNECT) {
                    LogUtils.i(TAG, "设备断开连接");
                    if (isTryToConnectDevice) {
                        //正在尝试连接设备设备，发起重连
                        if (retryCount < Max_Retry_Count) {
                            retryCount++;
                            LogUtils.i(TAG, "连接失败，进行重连尝试，重连次数：" + retryCount);
                            mHandler.sendEmptyMessageDelayed(Msg_Connect_Device, 1000);
                        } else {
                            isTryToConnectDevice = false;
                            LogUtils.i(TAG, "超过最大重连次数，直接放着不管，等待超时处理");
                            Message overtimeMsg = new Message();
                            overtimeMsg.arg1 = Error_Ble_Server;
                            overtimeMsg.what = Msg_Connect_Fail;
                            overtimeMsg.obj = "连接失败，请稍后重试";
                            mHandler.sendMessage(overtimeMsg);
                        }
                    } else {
                        //连接突然断开
                        Message overtimeMsg = new Message();
                        overtimeMsg.arg1 = Error_Ble_Server;
                        overtimeMsg.what = Msg_Connect_Fail;
                        overtimeMsg.obj = "连接已断开";
                        mHandler.sendMessage(overtimeMsg);
                    }

                } else if (device.isConnected()) {
                    LogUtils.i(TAG, "连接成功，开始设置通知");
                    /*连接成功后，设置通知*/
                    setNotify(device);
                }
            }
        }

        @Override
        public void onConnectException(BleDevice device, int errorCode) {
            super.onConnectException(device, errorCode);
            LogUtils.i(TAG, "框架连接异常，等待超时机制");
//            tvStatus.setText("连接异常，异常状态码:" + errorCode);
        }

        @Override
        public void onConnectTimeOut(BleDevice device) {
            super.onConnectTimeOut(device);
//            Log.e(TAG, "onConnectTimeOut: " + device.getBleAddress());
//            tvStatus.setText("连接超时");

            LogUtils.i(TAG, "框架连接超时,等待超时机制");
            isTryToConnectDevice = false;
            Message overtimeMsg = new Message();
            overtimeMsg.arg1 = Error_Ble_Server;
            overtimeMsg.what = Msg_Connect_Fail;
            overtimeMsg.obj = "连接超时，请稍后重试";
            mHandler.sendMessage(overtimeMsg);
        }
    };

    /*设置通知的回调*/
    private void setNotify(BleDevice device) {
        /*连接成功后，设置通知*/
//        mBle.startNotify(device, mBleNotifyCallback);
        mBle.startNotify(device, notifyCallback);
    }


    BleNotiftCallback<BleDevice> notifyCallback = new BleNotiftCallback<BleDevice>() {
        @Override
        public void onChanged(BleDevice device, BluetoothGattCharacteristic characteristic) {
            if (characteristic != null) {
//                byte[] data = characteristic.getValue();
//                L.e(TAG, "onChanged==address:" + device.getBleAddress());
//
//                L.e(TAG, "onChanged==data:" + data != null ? HexUtil.encodeHexStr(data) : "");
//                    L.e(TAG, "设置通知成功，可以开始操作");

            }
        }

        @Override
        public void onNotifySuccess(BluetoothGatt gatt) {
            super.onNotifySuccess(gatt);
            L.e(TAG, "设置通知成功，可以开始操作");
            isTryToConnectDevice = false;
            mHandler.sendEmptyMessage(Msg_Connect_Success);
        }
    };

    public void toast(String content) {
        ToastMgr.show(content);
    }


    /**
     * 钥匙旋转动画
     */
    private void showLoading() {
        LoadDialog.show(mContext, "");
    }

    private void dismissLoading() {
        LoadDialog.dismiss(BleOperationActivity.this);
    }

    /**
     * 展示当前蓝牙服务有问题（Ble为空）提示退出重新登陆
     * 提示：当前系统蓝牙服务可能存在问题，请退出本功能后重新尝试。如果持续扫不到设备，请尝试关闭系统蓝牙服务，重新开启后再尝试开门。
     */
    private void showExitDialog() {
        AlertDialog.Builder builder = new AlertDialog.Builder(BleOperationActivity.this);
        builder.setTitle("提示：");
        builder.setMessage("当前系统蓝牙服务可能存在问题，请退出重新尝试。如果持续扫不到设备，请尝试关闭系统蓝牙服务，重新开启后再尝试使用本功能。");
        //点击对话框以外的区域是否让对话框消失
        builder.setCancelable(false);
        //设置正面按钮
        builder.setPositiveButton("确定", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                dialog.dismiss();
                finish();
            }
        });

        AlertDialog dialog = builder.create();
        //显示对话框
        dialog.show();
    }


    /**
     * 通用信息提示框
     *
     * @param title
     * @param content
     */
    public void showCommonDialog(String title, String content) {
        new MaterialDialog.Builder(BleOperationActivity.this)
                .title(title)
                .content(content)
                .positiveText("确定")
                .show();
    }

}
